#ifndef TIEC_SYMBOL_H
#define TIEC_SYMBOL_H

#include "macro.h"
#include "foundation.h"
#include "data.h"

namespace NS_TIEC {

#define DECL_MODIFIER(name, value) static constexpr int64_t name = value;
  /// 修饰符类
  class Modifiers {
  public:
    DECL_MODIFIER(kStatic, 1)
    DECL_MODIFIER(kPublic, kStatic << 1)
    DECL_MODIFIER(kHidden, kPublic << 1)
    DECL_MODIFIER(kConst, kHidden << 1)
    DECL_MODIFIER(kVirtualMethod, kConst << 1)
    DECL_MODIFIER(kVirtualEvent, kVirtualMethod << 1)
    DECL_MODIFIER(kForbidExtends, kVirtualEvent << 1)
    DECL_MODIFIER(kForbidNew, kForbidExtends << 1)
    DECL_MODIFIER(kForbidOutput, kForbidNew << 1)
    DECL_MODIFIER(kGlobalClass, kForbidOutput << 1)
    DECL_MODIFIER(kAlias, kGlobalClass << 1)
    DECL_MODIFIER(kPlatformCode, kAlias << 1)
    DECL_MODIFIER(kDebug, kPlatformCode << 1)
    DECL_MODIFIER(kNullable, kDebug << 1)
    DECL_MODIFIER(kOperatorOverload, kNullable << 1)
    DECL_MODIFIER(kAutoSubscribe, kOperatorOverload << 1)
    DECL_MODIFIER(kAsyncMethod, kAutoSubscribe << 1)
    DECL_MODIFIER(kDeprecated, kAsyncMethod << 1)
    DECL_MODIFIER(kForbidPointer, kDeprecated << 1)
    constexpr static Int64 kLevelPackage = 1;
    constexpr static Int64 kLevelClass = kLevelPackage << 1;
    constexpr static Int64 kLevelMethod = kLevelClass << 1;
    constexpr static Int64 kLevelEvent = kLevelMethod << 1;
    constexpr static Int64 kLevelVariable = kLevelEvent << 1;
    constexpr static Int64 kLevelInvalid = kLevelVariable << 1;

    Modifiers();
    explicit Modifiers(Int64 modifier);

    /// 添加一个修饰符
    /// \param modifier 修饰符
    void add(Int64 modifier);

    /// 添加一个修饰符
    /// \param modifier 修饰符
    void operator<<(Int64 modifier);

    /// 移除一个修饰符
    /// \param modifier 修饰符
    void remove(Int64 modifier);

    /// 判断是否包含某个修饰符
    /// \param modifier 修饰符
    bool has(Int64 modifier) const;

    String toString() const;

  private:
    Int64 modifier_;
  };
#undef DECL_MODIFIER

  /// 方法类型
  enum struct MethodKind {
    // 普通方法
    kCommon = 0,
    // 属性读方法
    kGetter = 1,
    // 属性写方法
    kSetter = 2,
    // 定义事件
    kEventDeclare = 3,
  };

  enum struct TypeKind {
    kClass = 0,
    kArray,
    kTemplate,
    kTypeVariable,
    kVariant,
    kVoid,
    kNull
  };

  class Type {
  public:
    virtual TypeKind getKind() = 0;
  };

  template<typename T, typename = std::enable_if_t<std::is_base_of_v<Type, T>>>
  inline PTR<T> castTypeAs(const PTR<Type>& type) {
    return std::static_pointer_cast<T>(type);
  }

  enum struct SymbolKind {
    kPackage = 0,
    kClass,
    kTypeVar,
    kVariable,
    kMethod,
    kEvent,
  };

  /// Symbol包含的自定义数据
  struct SymbolData {
    List<PAIR<PTR<Name>, ConstValue>> values {};

    void addValue(const PTR<Name>& name, const ConstValue& value);
    bool hasValue(const PTR<Name>& name) const;
    bool hasValue(const PTR<Name>& name, const ConstValue& value) const;
    ConstValue& findValue(const PTR<Name>& name);
    ConstValue findValue(const PTR<Name>& name) const;

    template<typename Func, typename = std::enable_if_t<is_lambda_or_func<Func, void, const ConstValue&>>>
    void forEachValue(const PTR<Name>& name, Func&& consumer) {
      for (const PAIR<PTR<Name>, ConstValue>& pair : values) {
        if (pair.first == name) {
          std::forward<Func>(consumer)(pair.second);
        }
      }
    }
  };

  /// Symbol进行符号填充时的状态
  enum struct CompleteStatus {
    /// 符号填充的初始状态
    kEnterReady = 0,
    /// 符号填充时等待依赖的Symbol先填充
    kEnterPending,
    /// 符号填充已正式开始（进行中）
    kEnterStarted,
    /// 符号填充填充完毕
    kEnterDone,
    /// 等待依赖的成员变量类型推断（kAttr相关的Status只有VarSymbol会用到）
    kAttrPending,
    /// 变量的语义分析完毕
    kAttrDone,
    /// 输出分析完毕
    kAnalyzeDone,
    /// Lower完毕
    kLowerDone,
  };

  /// 符号基类
  class Symbol {
  public:
    /// 符号的原始名称
    PTR<Name> name;
    /// 修饰符
    Modifiers modifiers;
    /// 符号所处父级符号（比如 MethodSymbol 归属于 ClassSymbol）
    WPTR<Symbol> owner;
    /// 符号的类型表示
    PTR<Type> type;
    /// 源代码定义位置
    Origin origin;
    /// 符号包含的附加数据（一般由注解处理器附加）
    SymbolData data {};
    /// 经过改编后的符号名称（一般用作编译输出时修改符号输出名，如 rn_xx）
    String mangled_name;
    CompleteStatus status {CompleteStatus::kEnterReady};
    /// 符号是否被使用到了，编译输出时如果该属性为false则不进行输出
    bool is_used {false};

    virtual SymbolKind getKind() = 0;
  };

  template<typename T, typename = std::enable_if_t<std::is_base_of_v<Symbol, T>>>
  inline PTR<T> castSymbolAs(const PTR<Symbol>& symbol) {
    return std::static_pointer_cast<T>(symbol);
  }

  class ClassSymbol;
  class MethodSymbol;
  class Scope {
  public:
    Scope();
    Scope(const PTR<Scope>& parent, const PTR<ClassSymbol>& enclosing_class, const PTR<MethodSymbol>& enclosing_method);

    /// 获取作用域下所有符号
    /// @param recursive 是否递归获取
    virtual List<PTR<Symbol>> getSymbols(const bool recursive = false);

    /// 过滤作用域下所有符号
    /// @param filter 过滤函数
    /// @param recursive 是否递归获取
    template<typename Func, typename = std::enable_if_t<is_lambda_or_func<Func, bool, const PTR<Symbol>&>>>
    List<PTR<Symbol>> getSymbols(Func&& filter, const bool recursive = false) {
      List<PTR<Symbol>> result;
      for (const PTR<Symbol>& symbol : symbols_) {
        if (std::forward<Func>(filter)(symbol)) {
          result.add(symbol);
        }
      }
      if (recursive) {
        PTR<Scope> lock_parent = this->parent_.lock();
        while (lock_parent != nullptr) {
          for (const PTR<Symbol>& symbol : lock_parent->symbols_) {
            if (std::forward<Func>(filter)(symbol)) {
              result.add(symbol);
            }
          }
          lock_parent = lock_parent->parent_.lock();
        }
      }
      return result;
    }

    /// 获取作用域下指定名称的符号
    /// @param name 符号名称
    /// @param recursive 是否递归获取
    virtual List<PTR<Symbol>> getSymbolsByName(const PTR<Name>& name, const bool recursive = true);

    /// 获取作用域下指定名称的符号
    /// @param name 符号名称
    /// @param filter 过滤函数
    /// @param recursive 是否递归获取
    template<typename Func, typename = std::enable_if_t<is_lambda_or_func<Func, bool, const PTR<Symbol>&>>>
    List<PTR<Symbol>> getSymbolsByName(const PTR<Name>& name, Func&& filter, const bool recursive = true) {
      List<PTR<Symbol>> result;
      for (const PTR<Symbol>& symbol : symbols_) {
        if (symbol->name == name && std::forward<Func>(filter)(symbol)) {
          result.add(symbol);
        }
      }
      if (recursive) {
        PTR<Scope> lock_parent = this->parent_.lock();
        while (lock_parent != nullptr) {
          for (const PTR<Symbol>& symbol : lock_parent->symbols_) {
            if (symbol->name == name && std::forward<Func>(filter)(symbol)) {
              result.add(symbol);
            }
          }
          lock_parent = lock_parent->parent_.lock();
        }
      }
      return result;
    }

    /// 根据名称获取作用域下名称匹配的第一个符号
    /// @param name 名称
    /// @param recursive 是否递归获取
    virtual PTR<Symbol> getFirstByName(const PTR<Name>& name, const bool recursive = true);

    /// 根据名称获取作用域下名称匹配的第一个符号
    /// @param name 名称
    /// @param filter 过滤函数
    /// @param recursive 是否递归获取
    template<typename Func, typename = std::enable_if_t<is_lambda_or_func<Func, bool, const PTR<Symbol>&>>>
    PTR<Symbol> getFirstByName(const PTR<Name>& name, Func&& filter, const bool recursive = true) {
      PTR<Symbol> found = symbols_.findFirst([&name, &filter](const PTR<Symbol>& symbol) {
        return symbol->name == name && std::forward<Func>(filter)(symbol);
      });
      if (found != nullptr) {
        return found;
      }
      if (recursive) {
        PTR<Scope> lock_parent = this->parent_.lock();
        while (lock_parent != nullptr) {
          found = lock_parent->symbols_.findFirst([&name, &filter](const PTR<Symbol>& symbol) {
            return symbol->name == name && std::forward<Func>(filter)(symbol);
          });
          if (found != nullptr) {
            return found;
          }
          lock_parent = lock_parent->parent_.lock();
        }
      }
      return nullptr;
    }

    /// 根据名称获取作用域下名称匹配的第一个符号，并强转为指定类型
    /// @param name 名称
    /// @param filter 过滤函数
    /// @param recursive 是否递归获取
    template<typename T, typename Func, 
      typename = std::enable_if_t<std::is_base_of_v<Symbol, T> && is_lambda_or_func<Func, bool, const PTR<Symbol>&>>>
    PTR<T> getFirstByNameAs(const PTR<Name>& name, Func&& filter, const bool recursive = true) {
      return std::static_pointer_cast<T>(getFirstByName(name, std::forward<Func>(filter), recursive));
    }

    /// 根据名称获取作用域下匹配过滤函数的第一个符号
    /// @param filter 过滤函数
    /// @param recursive 是否递归获取
    template<typename Func, typename = std::enable_if_t<is_lambda_or_func<Func, bool, const PTR<Symbol>&>>>
    PTR<Symbol> getFirst(Func&& filter, const bool recursive = false) {
      for (const PTR<Symbol>& symbol : symbols_) {
        if (std::forward<Func>(filter)(symbol)) {
          return symbol;
        }
      }
      if (recursive) {
        PTR<Scope> lock_parent = this->parent_.lock();
        while (lock_parent != nullptr) {
          for (const PTR<Symbol>& symbol : lock_parent->symbols_) {
            if (std::forward<Func>(filter)(symbol)) {
              return symbol;
            }
          }
          lock_parent = lock_parent->parent_.lock();
        }
      }
      return nullptr;
    }

    /// 判断当前作用域下是否包含指定Symbol
    /// @param symbol 传入的Symbol
    virtual bool contains(const PTR<Symbol>& symbol);

    /// 判断当前作用域下是否有符合条件的Symbol
    /// @param filter 过滤条件
    template<typename Func, typename = std::enable_if_t<is_lambda_or_func<Func, bool, const PTR<Symbol>&>>>
    bool containsIf(Func&& filter) {
      return symbols_.containsIf(std::forward<Func>(filter));
    }

    /// 当前作用域符号是否为空
    virtual bool isEmpty() const;

    /// 遍历当前作用域下所有Symbol
    /// @param consumer 遍历函数 
    template<typename Func, typename = std::enable_if_t<is_lambda_or_func<Func, void, const PTR<Symbol>&>>>
    void forEachSymbol(Func&& consumer) {
      for (const PTR<Symbol>& symbol : symbols_) {
        std::forward<Func>(consumer)(symbol);
      }
    }

    /// 判断当前作用域下有没有重复的符号（比如同名变量）
    /// @param symbol Symbol
    /// @return 如果有重名符号则返回true
    bool hasDuplicateSymbol(const PTR<Symbol>& symbol) const;

    /// 判断当前作用域下有没有遮蔽外层作用域的变量
    /// @param symbol Symbol
    /// @return 如果有遮蔽的符号则返回true
    bool hasShadowedSymbol(const PTR<Symbol>& symbol) const;

    /// 获取当前作用域的父级作用域
    PTR<Scope> getEnclosingScope() const;

    /// 获取当前作用域所处类Symbol
    PTR<ClassSymbol> getEnclosingClass() const;

    /// 获取当前作用域所处方法/事件的Symbol
    PTR<MethodSymbol> getEnclosingMethod() const;
  protected:
    List<PTR<Symbol>> symbols_;
    WPTR<Scope> parent_;
    WPTR<ClassSymbol> klass_;
    WPTR<MethodSymbol> method_;
  };

  class MutableScope : public Scope {
  public:
    MutableScope();
    MutableScope(const PTR<MutableScope>& parent, const PTR<ClassSymbol>& enclosing_class, const PTR<MethodSymbol>& enclosing_method);

    /// 在当前作用域下添加一个Symbol
    /// @param symbol 要添加的Symbol
    void addSymbol(const PTR<Symbol>& symbol);

    /// 在当前作用域下移除一个Symbol
    /// @param symbol 要移除的Symbol
    void removeSymbol(const PTR<Symbol>& symbol);
  };

  class PackageSymbol : public Symbol {
  public:
    SymbolKind getKind() override;
  };

  class TypeVarSymbol : public Symbol {
  public:
    SymbolKind getKind() override;
  };

  class VarSymbol : public Symbol {
  public:
    /// 是否为参数
    bool is_parameter {false};
    /// 参数是否有默认值（即可选）
    bool is_optional {false};
    /// 变量初始值引用的符号
    List<PTR<Symbol>> initializer_refs;
    /// 常量值
    ConstValue value {ConstValue::kNull};

    SymbolKind getKind() override;
    bool isClassMember() const;
  };

  class MethodSymbol : public Symbol {
  public:
    /// 方法类型
    MethodKind method_kind {MethodKind::kCommon};
    /// overrides的父类方法
    PTR<MethodSymbol> overrides_meta;
    /// 参数列表
    List<PTR<VarSymbol>> params;
    /// 方法体里面所有语句/表达式引用的符号
    List<PTR<Symbol>> body_refs;

    SymbolKind getKind() override;
  };

  class EventSymbol : public MethodSymbol {
  public:
    /// 事件对应的定义事件
    PTR<MethodSymbol> meta;
    /// 类成员事件对象对应的类成员变量或当前类Symbol
    PTR<Symbol> obj_sym;
    /// 事件里捕获的局部变量，用于对事件生成外部方法时放入参数传参
    List<PTR<VarSymbol>> captured_locals;
    /// 是否为类级别事件
    bool is_class_level {false};

    SymbolKind getKind() override;
  };

  class ClassSymbol : public Symbol {
  public:
    /// 完整类名（包含包名）
    PTR<Name> full_name;
    /// 模板类型参数
    List<PTR<TypeVarSymbol>> params;
    /// 成员
    PTR<MutableScope> members;
    /// 父类
    PTR<ClassSymbol> super;
    /// 本对象
    PTR<VarSymbol> this_sym;
    /// 值输出规则名称
    PTR<Name> value_rule_name;
    /// 值输入类型（接受输入类型的值，通过值输出规则转换为值输出类型）
    PTR<Type> input_type;
    /// 值输出类型（除了基本类型之外，可能还为文件路径或者颜色值，就看SymbolData有没有key为文件路径或者颜色值）
    PTR<Type> output_type;
    /// 嵌入式代码内引用的符号
    List<PTR<Symbol>> code_refs;
    /// 当前类引用到的所有类（类似Java的import，C++的#include），在符号引用分析时赋值
    Set<PTR<ClassSymbol>> import_classes;

    SymbolKind getKind() override;

    /// 获取PackageSymbol
    PTR<PackageSymbol> getPackage() const;

    /// 获取类的包名
    PTR<Name> getPackageName() const;

    /// 判断类是否为模板类，即包含模板参数
    bool isTemplateClass() const;

    /// 根据名称获取类成员
    /// @param name 名称
    /// @param filter 过滤函数
    /// @param recursive 是否递归获取，如果递归获取，会向上查找父类成员
    template<typename Func, typename = std::enable_if_t<is_lambda_or_func<Func, bool, const PTR<Symbol>&>>>
    PTR<Symbol> getMember(const PTR<Name>& name, Func&& filter, const bool recursive = true) {
      PTR<Symbol> found = members->getFirstByName(name, std::forward<Func>(filter), false);
      if (found != nullptr) {
        return found;
      }
      if (recursive) {
        PTR<ClassSymbol> super_sym = super;
        while (super_sym != nullptr) {
          found = super_sym->members->getFirstByName(name, std::forward<Func>(filter), false);
          if (found != nullptr) {
            return found;
          }
          super_sym = super_sym->super;
        }
      }
      return nullptr;
    }

    /// 根据名称获取类成员，并强转为指定类型
    /// @param name 名称
    /// @param filter 过滤函数
    /// @param recursive 是否递归获取，如果递归获取，会向上查找父类成员
    template<typename T, typename Func,
    typename = std::enable_if_t<std::is_base_of_v<Symbol, T> && is_lambda_or_func<Func, bool, const PTR<Symbol>&>>>
    PTR<T> getMemberAs(const PTR<Name>& name, Func&& filter, const bool recursive = true) {
      return std::static_pointer_cast<T>(getMember(name, filter, recursive));
    }
  };

  class ClassType : public Type {
  public:
    WPTR<ClassSymbol> symbol;
    // 父类类型
    PTR<Type> super;

    TypeKind getKind() override;
  };

  class ArrayType : public Type {
  public:
    PTR<Type> prefix;

    TypeKind getKind() override;
  };

  class TypeVariable : public Type {
  public:
    WPTR<TypeVarSymbol> symbol;
    // 默认实现类型
    PTR<Type> default_type;

    TypeKind getKind() override;
  };

  /// 模板类型，包含模板原始类型定义和模板实现类型
  /// ClassType中的 symbol 指的是模板类型最终定义的类，每个模板实现类型，都会生成新的ClassSymbol
  class TemplateType : public ClassType {
  public:
    /// 模板原始定义的ClassSymbol，如果是模板原始定义，这里的meta和symbol相同，如果是模板实现则meta和symbol不同
    WPTR<ClassSymbol> meta;
    /// @brief 模板实现参数
    List<PTR<Type>> args;

    TypeKind getKind() override;
  };

  class VariantType : public Type {
  public:
    TypeKind getKind() override;
  };

  class VoidType : public Type {
  public:
    TypeKind getKind() override;
  };

  class NullType : public Type {
  public:
    TypeKind getKind() override;
  };

  template<typename Result, typename... Params>
  class SymbolVisitor {
  public:
#define CASE_VISIT_SYMBOL(sym_kind, sym_class) \
  case sym_kind: { \
    const PTR<sym_class> sym = std::static_pointer_cast<sym_class>(symbol); \
    return visit##sym_class(sym, params...); \
  }
    Result visitSymbol(const PTR<Symbol>& symbol, Params... params) {
      if (symbol == nullptr) {
        if constexpr (std::is_void_v<Result>) {
          return;
        } else {
          return {};
        }
      }
      switch (symbol->getKind()) {
        CASE_VISIT_SYMBOL(SymbolKind::kPackage, PackageSymbol)
        CASE_VISIT_SYMBOL(SymbolKind::kClass, ClassSymbol)
        CASE_VISIT_SYMBOL(SymbolKind::kTypeVar, TypeVarSymbol)
        CASE_VISIT_SYMBOL(SymbolKind::kVariable, VarSymbol)
        CASE_VISIT_SYMBOL(SymbolKind::kMethod, MethodSymbol)
        CASE_VISIT_SYMBOL(SymbolKind::kEvent, EventSymbol)
      default:
        throw std::runtime_error("SymbolVisitor::visitSymbol(): Unknown symbol kind");
      }
    }
#undef CASE_VISIT_SYMBOL
#define VISIT_SYMBOL(sym_class) \
  virtual Result visit ##sym_class(const PTR<sym_class>& symbol, Params... params) { \
    if constexpr (std::is_void_v<Result>) { \
      return; \
    } else { \
      return {}; \
    } \
  }
    VISIT_SYMBOL(PackageSymbol)
    VISIT_SYMBOL(ClassSymbol)
    VISIT_SYMBOL(TypeVarSymbol)
    VISIT_SYMBOL(VarSymbol)
    VISIT_SYMBOL(MethodSymbol)
    VISIT_SYMBOL(EventSymbol)
#undef VISIT_SYMBOL
  };

  template<typename Result, typename... Params>
  class TypeVisitor {
  public:
#define CASE_VISIT_TYPE(type_kind, type_class) \
  case type_kind: { \
    const PTR<type_class> cast_type = std::static_pointer_cast<type_class>(type); \
    return visit##type_class(cast_type, params...); \
  }
    Result visitType(const PTR<Type>& type, Params... params) {
      if (type == nullptr) {
        if constexpr (std::is_void_v<Result>) {
          return;
        } else {
          return {};
        }
      }
      switch (type->getKind()) {
        CASE_VISIT_TYPE(TypeKind::kClass, ClassType)
        CASE_VISIT_TYPE(TypeKind::kArray, ArrayType)
        CASE_VISIT_TYPE(TypeKind::kTypeVariable, TypeVariable)
        CASE_VISIT_TYPE(TypeKind::kTemplate, TemplateType)
        CASE_VISIT_TYPE(TypeKind::kVariant, VariantType)
        CASE_VISIT_TYPE(TypeKind::kVoid, VoidType)
        CASE_VISIT_TYPE(TypeKind::kNull, NullType)
      default:
        throw std::runtime_error("TypeVisitor::visitType(): Unknown type kind");
      }
    }
#undef CASE_VISIT_TYPE
#define VISIT_TYPE(type_class) \
  virtual Result visit ##type_class(const PTR<type_class>& type, Params... params) { \
    if constexpr (std::is_void_v<Result>) { \
      return; \
    } else { \
      return {}; \
    } \
  }
    VISIT_TYPE(ClassType)
    VISIT_TYPE(ArrayType)
    VISIT_TYPE(TypeVariable)
    VISIT_TYPE(TemplateType)
    VISIT_TYPE(VariantType)
    VISIT_TYPE(VoidType)
    VISIT_TYPE(NullType)
#undef VISIT_TYPE
  };

  /// Symbol比较器，用于比较Symbol内容是否相同
  class SymbolComparator : public SymbolVisitor<bool, const PTR<Symbol>&> {
  public:
    bool areEqualSymbols(const PTR<Symbol>& a, const PTR<Symbol>& b);

    template<typename T, typename = std::enable_if_t<std::is_base_of_v<Symbol, T>>>
    bool areEqualSymbols(const List<PTR<T>>& a, const List<PTR<T>>& b) {
      if (a.size() != b.size()) {
        return false;
      }
      for (size_t i = 0; i < a.size(); i++) {
        const PTR<T>& symbol_a = a[i];
        const PTR<T>& symbol_b = b[i];
        if (!areEqualSymbols(symbol_a, symbol_b)) {
          return false;
        }
      }
      return true;
    }

    /*bool areEqualSymbols(const List<PTR<Symbol>>& a, const List<PTR<Symbol>>& b);
    bool areEqualSymbols(const List<PTR<VarSymbol>>& a, const List<PTR<VarSymbol>>& b);
    bool areEqualSymbols(const List<PTR<TypeVarSymbol>>& a, const List<PTR<TypeVarSymbol>>& b);*/

    bool visitPackageSymbol(const PTR<PackageSymbol>& symbol, const PTR<Symbol>& param) override;
    bool visitClassSymbol(const PTR<ClassSymbol>& symbol, const PTR<Symbol>& param) override;
    bool visitTypeVarSymbol(const PTR<TypeVarSymbol>& symbol, const PTR<Symbol>& param) override;
    bool visitVarSymbol(const PTR<VarSymbol>& symbol, const PTR<Symbol>& param) override;
    bool visitMethodSymbol(const PTR<MethodSymbol>& symbol, const PTR<Symbol>& param) override;
    bool visitEventSymbol(const PTR<EventSymbol>& symbol, const PTR<Symbol>& param) override;
  };

  /// Symbol文本化工具，可将Symbol转化为文本表示
  class SymbolStringifier : public SymbolVisitor<String, NullValue&> {
  public:
    /// 将Symbol进行文本化
    /// @param symbol 要文本化的Symbol
    /// @return Symbol的文本化唯一标识
    String stringify(const PTR<Symbol>& symbol);

    String visitPackageSymbol(const PTR<PackageSymbol>& symbol, NullValue& param) override;
    String visitClassSymbol(const PTR<ClassSymbol>& symbol, NullValue& param) override;
    String visitTypeVarSymbol(const PTR<TypeVarSymbol>& symbol, NullValue& param) override;
    String visitVarSymbol(const PTR<VarSymbol>& symbol, NullValue& param) override;
    String visitMethodSymbol(const PTR<MethodSymbol>& symbol, NullValue& param) override;
    String visitEventSymbol(const PTR<EventSymbol>& symbol, NullValue& param) override;
  };

  /// Symbol拷贝器，用于完整的拷贝Symbol
  template<typename... Params>
  class SymbolCopier : public SymbolVisitor<PTR<Symbol>, Params...> {
  public:
    template<typename T, typename = std::enable_if_t<std::is_base_of_v<Symbol, T>>>
    PTR<T> copySymbol(const PTR<T>& symbol, Params... params) {
      return std::static_pointer_cast<T>(SymbolVisitor<PTR<Symbol>, Params...>::visitSymbol(symbol, params...));
    }

    template<typename T, typename = std::enable_if_t<std::is_base_of_v<Symbol, T>>>
    List<PTR<T>> copySymbols(const List<PTR<T>>& symbols, Params... params) {
      List<PTR<T>> result;
      for (const PTR<T>& symbol : symbols) {
        result.add(copySymbol<T>(symbol, params...));
      }
      return result;
    }

    PTR<Symbol> visitPackageSymbol(const PTR<PackageSymbol>& symbol, Params... params) override {
      const PTR<PackageSymbol> new_sym = MAKE_PTR<PackageSymbol>();
      new_sym->name = symbol->name;
      new_sym->owner = symbol->owner;
      new_sym->modifiers = symbol->modifiers;
      new_sym->type = processType(symbol->type, params...);
      new_sym->origin = symbol->origin;
      new_sym->data = symbol->data;
      new_sym->mangled_name = symbol->mangled_name;
      return new_sym;
    }

    PTR<Symbol> visitClassSymbol(const PTR<ClassSymbol>& symbol, Params... params) override {
      const PTR<ClassSymbol> new_sym = MAKE_PTR<ClassSymbol>();
      new_sym->name = symbol->name;
      new_sym->owner = symbol->owner;
      new_sym->modifiers = symbol->modifiers;
      new_sym->type = processType(symbol->type, params...);
      new_sym->origin = symbol->origin;
      new_sym->data = symbol->data;
      new_sym->mangled_name = symbol->mangled_name;
      new_sym->full_name = symbol->full_name;
      new_sym->super = symbol->super;
      new_sym->params = copySymbols<TypeVarSymbol>(symbol->params, params...);
      return new_sym;
    }

    PTR<Symbol> visitVarSymbol(const PTR<VarSymbol>& symbol, Params... params) override {
      const PTR<VarSymbol> new_sym = MAKE_PTR<VarSymbol>();
      new_sym->name = symbol->name;
      new_sym->owner = symbol->owner;
      new_sym->modifiers = symbol->modifiers;
      new_sym->type = processType(symbol->type, params...);
      new_sym->origin = symbol->origin;
      new_sym->data = symbol->data;
      new_sym->mangled_name = symbol->mangled_name;
      new_sym->is_parameter = symbol->is_parameter;
      new_sym->value = symbol->value;
      return new_sym;
    }

    PTR<Symbol> visitMethodSymbol(const PTR<MethodSymbol>& symbol, Params... params) override {
      const PTR<MethodSymbol> new_sym = MAKE_PTR<MethodSymbol>();
      new_sym->name = symbol->name;
      new_sym->owner = symbol->owner;
      new_sym->modifiers = symbol->modifiers;
      new_sym->type = processType(symbol->type, params...);
      new_sym->origin = symbol->origin;
      new_sym->data = symbol->data;
      new_sym->mangled_name = symbol->mangled_name;
      new_sym->params = copySymbols<VarSymbol>(symbol->params, params...);
      return new_sym;
    }

    PTR<Symbol> visitEventSymbol(const PTR<EventSymbol>& symbol, Params... params) override {
      const PTR<EventSymbol> new_sym = MAKE_PTR<EventSymbol>();
      new_sym->name = symbol->name;
      new_sym->owner = symbol->owner;
      new_sym->modifiers = symbol->modifiers;
      new_sym->type = processType(symbol->type, params...);
      new_sym->origin = symbol->origin;
      new_sym->data = symbol->data;
      new_sym->mangled_name = symbol->mangled_name;
      new_sym->params = copySymbols<VarSymbol>(symbol->params, params...);
      new_sym->meta = symbol->meta;
      new_sym->is_class_level = symbol->is_class_level;
      return new_sym;
    }

    PTR<Symbol> visitTypeVarSymbol(const PTR<TypeVarSymbol>& symbol, Params... params) override {
      const PTR<TypeVarSymbol> new_sym = MAKE_PTR<TypeVarSymbol>();
      new_sym->name = symbol->name;
      new_sym->owner = symbol->owner;
      new_sym->modifiers = symbol->modifiers;
      new_sym->type = processType(symbol->type, params...);
      new_sym->origin = symbol->origin;
      new_sym->data = symbol->data;
      new_sym->mangled_name = symbol->mangled_name;
      return new_sym;
    }

    virtual PTR<Type> processType(const PTR<Type>& type, Params... params) {
      return type;
    }
  };

  /// Type比较器，用于检测两个Type是否完全相同（地址相同）
  class TypeEqualityComparator : public TypeVisitor<bool, const PTR<Type>&> {
  public:
    bool areEqualTypes(const PTR<Type>& required, const PTR<Type>& assignment);
    bool areEqualTypes(const List<PTR<Type>>& required, const List<PTR<Type>>& assignment);

    bool visitClassType(const PTR<ClassType>& type, const PTR<Type>& param) override;
    bool visitArrayType(const PTR<ArrayType>& type, const PTR<Type>& param) override;
    bool visitTypeVariable(const PTR<TypeVariable>& type, const PTR<Type>& param) override;
    bool visitTemplateType(const PTR<TemplateType>& type, const PTR<Type>& param) override;
  };

  /// Type比较器（IDE专用），用于检测两个Type是否完全相同（内容相同）
  class IDETypeEqualityComparator : public TypeEqualityComparator {
  public:
    IDETypeEqualityComparator();

    bool visitClassType(const PTR<ClassType>& type, const PTR<Type>& param) override;
  private:
    UPTR<SymbolComparator> sym_cmp_;
  };

  /// Type比较器，用于检测Type赋值是否正确（只比较Symbol地址，不比较内容）
  class TypeComparator : public TypeVisitor<bool, const PTR<Type>&> {
  public:
    explicit TypeComparator(const PTR<ClassSymbol>& global_super_class);
    virtual bool isTypeAssignableFrom(const PTR<Type>& required, const PTR<Type>& assignment);
    bool areTypesAssignableFrom(const List<PTR<Type>>& required, const List<PTR<Type>>& assignment);

    bool visitClassType(const PTR<ClassType>& type, const PTR<Type>& param) override;
    bool visitArrayType(const PTR<ArrayType>& type, const PTR<Type>& param) override;
    bool visitTypeVariable(const PTR<TypeVariable>& type, const PTR<Type>& param) override;
    bool visitTemplateType(const PTR<TemplateType>& type, const PTR<Type>& param) override;
  protected:
    PTR<ClassType> global_super_type_;
    virtual bool isGlobalSuperType(const PTR<Type>& type);
  };

  /// IDE专用的Type比较器，用于检测Type赋值是否正确（会比较Symbol内容，而不是比较地址）
  class IDETypeComparator : public TypeComparator {
  public:
    explicit IDETypeComparator(const PTR<ClassSymbol>& global_super_class);

    bool visitClassType(const PTR<ClassType>& type, const PTR<Type>& param) override;
  protected:
    bool isGlobalSuperType(const PTR<Type>& type) override;
  private:
    UPTR<IDETypeEqualityComparator> eq_cmp_;
    UPTR<SymbolComparator> sym_cmp;
  };

  using TypeVariableReplaceMap = HashMap<PTR<TypeVariable>, PTR<Type>>;
  /// 类型替换器，通过传入一个类型替换表，将类型进行替换
  class TypeReplacer : TypeVisitor<PTR<Type>, const TypeVariableReplaceMap&> {
  public:
    PTR<Type> replaceType(const PTR<Type>& type, const TypeVariableReplaceMap& type_replacement);

    PTR<Type> visitClassType(const PTR<ClassType>& type, const TypeVariableReplaceMap& param) override;
    PTR<Type> visitArrayType(const PTR<ArrayType>& type, const TypeVariableReplaceMap& param) override;
    PTR<Type> visitTypeVariable(const PTR<TypeVariable>& type, const TypeVariableReplaceMap& param) override;
    PTR<Type> visitTemplateType(const PTR<TemplateType>& type, const TypeVariableReplaceMap& param) override;
    PTR<Type> visitVariantType(const PTR<VariantType>& type, const TypeVariableReplaceMap& param) override;
    PTR<Type> visitVoidType(const PTR<VoidType>& type, const TypeVariableReplaceMap& param) override;
    PTR<Type> visitNullType(const PTR<NullType>& type, const TypeVariableReplaceMap& param) override;
  };

  /// Symbol工具类封装
  class SymbolUtil {
  public:
    /// 根据一个Symbol，查找到其所处类
    /// @param symbol 类中的Symbol（可以为局部Symbol）
    /// @return symbol所处类ClassSymbol
    static PTR<ClassSymbol> findEnclosingClass(const PTR<Symbol>& symbol);

    /// 根据一个Symbol，查找到其所处包名
    /// @param symbol Symbol（可以为局部Symbol）
    /// @return symbol所处包名
    static PTR<PackageSymbol> findEnclosingPackage(const PTR<Symbol>& symbol);

    /// 根据一个Symbol，查找到其所处方法
    /// @param symbol 方法中的局部变量Symbol
    /// @return symbol所处方法MethodSymbol
    static PTR<MethodSymbol> findEnclosingMethod(const PTR<Symbol>& symbol);

    /// 判断两个Symbol是否相同
    /// @param a Symbol1
    /// @param b Symbol2
    /// @param ide_mode 是否为IDE模式（IDE模式比较内容，编译模式比较地址）
    static bool areEqualSymbols(const PTR<Symbol>& a, const PTR<Symbol>& b, const bool ide_mode = false);

    /// 判断某个类是否继承于目标类
    /// @param klass 子类
    /// @param target 父类
    /// @param global_super_class 全局基础类（如果没有则为nullptr）
    /// @param ide_mode 是否为IDE模式，如果是IDE模式，则比较内容不比较地址
    static bool isInherited(const PTR<ClassSymbol>& klass, const PTR<ClassSymbol>& target,
      const PTR<ClassSymbol>& global_super_class = nullptr, const bool ide_mode = false);

    /// 将符号文本化
    /// @param symbol 符号
    /// @return 文本化之后的唯一表示
    static String stringify(const PTR<Symbol>& symbol);
  };

  /// Type工具类封装
  class TypeUtil {
  public:
    /// 判断某个类型是否继承于目标类类型/模板类型，如果是模板类型之间的继承，那么只有实现类型之间才有继承关系
    /// @code
    /// 类 我的集合<T> : 集合<T>
    /// 类 文本集合 : 我的集合<文本>
    /// `我的集合<文本>` 继承的是 `集合<文本>`，而不是 `集合<T>`
    /// @endcode
    /// @param type 赋值类型
    /// @param target 目标类型
    /// @param ide_mode 是否为IDE模式
    static bool isInherited(const PTR<ClassType>& type,
      const PTR<ClassType>& target, const bool ide_mode = false);

    /// 判断具体模板实现类型是否为指定模板元类型的实现
    /// @code
    /// 类 我的集合<T> : 集合<T>
    /// 类 文本集合 : 我的集合<文本>
    /// `我的集合<文本>` 是 `我的集合<T>` 的实现，也是 `集合<T>` 的实现
    /// @endcode
    /// @param type 模板实现类型
    /// @param template_meta 原始模板类型
    /// @param ide_mode 是否为IDE模式
    static bool isInstance(const PTR<ClassType>& type,
      const PTR<TemplateType>& template_meta, const bool ide_mode = false);

    /// 获取模板实现类的具体类型参数
    /// @param type 模板实现类型，也许是模板实现类的子类
    /// @param template_meta 原始模板类型
    /// @param ide_mode 是否为IDE模式
    static List<PTR<Type>> getTemplateInstanceArgs(
      const PTR<ClassType>& type, const PTR<TemplateType>& template_meta, const bool ide_mode = false);

    /// 判断指定类型是否可以作为ClassType来使用
    /// @param type 类型
    /// @return 如果可以强转为ClassType来使用，则返回 true（排除nullptr）
    static inline bool canBeClassType(const PTR<Type>& type) {
      if (type == nullptr) {
        return false;
      }
      return type->getKind() == TypeKind::kClass || type->getKind() == TypeKind::kTemplate;
    }
  };

  // =====================================一些常用的过滤函数====================================
  bool kFunc_isCommonMethod(const PTR<Symbol>& symbol);
  bool kFunc_isGetterMethod(const PTR<Symbol>& symbol);
  bool kFunc_isSetterMethod(const PTR<Symbol>& symbol);
  bool kFunc_isDeclareEvent(const PTR<Symbol>& symbol);
  bool kFunc_isDeclareOrVirtualEvent(const PTR<Symbol>& symbol);
  bool kFunc_isCommonOrGetterMethod(const PTR<Symbol>& symbol);
  bool kFunc_isCommonMethodOrDeclareEvent(const PTR<Symbol>& symbol);
  bool kFunc_isVariable(const PTR<Symbol>& symbol);
  bool kFunc_isVarOrGetter(const PTR<Symbol>& symbol);
  bool kFunc_isVarOrSetter(const PTR<Symbol>& symbol);
  bool kFunc_isAny(const PTR<Symbol>& symbol);

  // =====================================辅助函数==============================================

  /// 将 MethodKind 转为字符串输出
  /// @param kind MethodKind
  /// @return MethodKind 对应的字符串
  String methodKindToString(const MethodKind& kind);
}

#endif //TIEC_SYMBOL_H
